from datetime import datetime

from flask import current_app, request
from flask_restful import Resource, inputs

from common.models.user import User
from heima_toutiao.apps.users.constants import SMS_CODE_EXPIRE
from heima_toutiao.apps.utils.token import generic_login_token
from common.cache.user import UserFansCache

#查询数据
class UserInfoResource(Resource):

    def get(self):
        user = User.query.filter_by(id=1).first()

        user_data = {
            'id': user.id,
            'mobile': user.mobile,
            'name': user.name,
            'photo': user.profile_photo or '',
            'is_media': user.is_media,
            'intro': user.introduction or '',
            'certi': user.certificate or '',
        }

        return user_data
import json
#查询redis缓存
class CacheUserInfoResource(Resource):

    def get(self):
        redis_data=current_app.redis_cli.get(1)
        user_data=json.loads(redis_data.decode())
        return user_data
    #用户第一次将数据库中的数据保存到缓存
    def post(self):
        user = User.query.filter_by(id=1).first()

        user_data = {
            'id': user.id,
            'mobile': user.mobile,
            'name': user.name,
            'photo': user.profile_photo or '',
            'is_media': user.is_media,
            'intro': user.introduction or '',
            'certi': user.certificate or '',
        }

        current_app.redis_cli.set(1, json.dumps(user_data))

        return {'message':'ok'}
'''
短信验证码接口文档
请求方式：get
请求参数：mobile  str 必传 路径传参
请求路径：/app/v1_0/sms/codes/<mobile>/
响应： {    "message": "ok",    "data": {        "mobile": "18310820688"    }}
message   data  mobile
'''
# 随机模块
from random import randint
# 连接redis数据库
from heima_toutiao import redis_cli, db
class SMScodeResource(Resource):
    def get(self,mobile):
        # 1.生成随机验证码
        code = '%06d'%randint(0,999999)
        # 2.把随机验证码保存起来
        redis_cli.setex(mobile,SMS_CODE_EXPIRE,code)
        # 3.发送短信验证码----容联云
        # 4.返回响应
        return {
            'mobile':mobile
        }
'''
登录功能接口文档
请求方式：post
请求路径： /app/v1_0/authorizations
请求参数：mobile    code   必传
响应：message data token
'''
########业务逻辑
#1.查询数据库  查看是否有这个手机号的用户
# 有  更新数据---记录用户最近的登录时间
# 没有  注册----把用户信息保存在数据库里
#2.状态保持---token
# 设置两个token--一个2小时---一个14天  如果2小时的token过期了 就根据14天的去刷新
from flask_restful import reqparse,abort
class LoginResource(Resource):
    def post(self):

        # 1.接收数据---实例化FRF中的解析器类
        rp = reqparse.RequestParser()
        # 添加要解析的数据
        # required = False,
        # type = text_type,
        # location = ('json', 'values',),
        # help = None,
        rp.add_argument(
            'mobile',
            required = True,
            location = 'json',
            type = inputs.regex('1[3-9]\d{9}'),
            help='请输入正确的手机号'
        )
        rp.add_argument(
            'code',
            required = True,
            location = 'json',
            type = inputs.regex('\d{6}'),
            help='验证码不符合规则'
        )
        # 提起数据
        data = rp.parse_args()
        mobile = data.get('mobile')
        code = data.get('code')
        # 2.校验参数
        # redis_code = redis_cli.get(mobile)
        # if redis_code is None:
        #     abort(400)
        # if redis_code.decode() != code:
        #     abort(400)
        # 3.业务逻辑
        # 查询数据库是否有这个手机号的用户---在数据库交互的时候可能出错
        try:
            user = User.query.filter_by(mobile=mobile).first()
        except Exception as e:
            current_app.logger.error(e)

        if user is None:
            # 如果没有  创建
            a = User(
                mobile=mobile,
                name=mobile,
                last_login=datetime.now()
            )
            # 使用雪花id生成器   不用系统生成id
            user.id = current_app.worker.get_id()
            db.session.add(a)
            db.session.commit()
        # 有  更新时间
        else:
            user.last_login=datetime.now()
            db.session.commit()
        # 业务逻辑上 生成两个token  需要接受
        token,refresh_token = generic_login_token(user.id)


        # 添加缓存
        from common.cache.user import UserinfoCache
        UserinfoCache(user.id).save(user)


        # 4.返回
        return {
            'token':token,
            'refresh_token':refresh_token
        }
    # 2小时的token会失效  当失效了 需要去重新刷新token
    '''
    刷新token接口文档
    请求方式：put
    请求参数：token
    请求路径：/app/v1_0/authorizations
    响应：token----重新生成的token
    '''
    def put(self):
        # 如果传递的token 在有效期内 . 有用户的id 并且 is_refresh 是True
        if g.user_id and g.is_refresh:

            #重新生成token
            token, refresh_token = generic_login_token(g.user_id)

            return {
                'token':token
            }
        else:
            return {},403

'''
个人中心接口文档
请求方式：get
请求参数：token
请求路径：/app/v1_0/user
响应：{
    "message": "OK",
    "data": {
        "id": 1155,
        "name": "18310820688",
        "photo": "xxxxx",
        "intro": "xxx",
        "art_count": 0,
        "follow_count": 0,
        "fans_count": 0
    }
}
'''
from flask import g
from heima_toutiao.apps.utils.decorators import login_required
class UserCenterResouce(Resource):
    # 在访问个人中心的时候  用户必须要先登录  自定义登录验证装饰器  ---给类使用>>method_decorators = [我们定义的装饰器]
    method_decorators = [login_required]
    def get(self):
        # 获取用户id---token中
        user_id=g.user_id
        # 提取参数---根据用户id获取用户信息
        # 业务逻辑
        # 1.从redis中查询缓存数据---有直接返回
        from common.cache.user import UserinfoCache
        data =  UserinfoCache(user_id).get()
        return data
        # 2.没有缓存数据---查询mysql---把查询的数据缓存起来
# 关注用户
'''
需求
    关注用户 和 取消     ---必须要登录才能操作
前段
    发送ajax请求  携带token
后端
    请求方式：post
    请求路径：/app/v1_0/user/followings
    请求参数：token  target---目标用户
    响应：target
'''
from common.models.user import Relation
from common.cache.user import UserinfoCache

class FollowResource(Resource):
    # 必须登录
    method_decorators = [login_required]
    def post(self):
        '''
        1.接受参数
        2.验证参数
        3.业务逻辑
        4.响应
        :return:
        '''
        # 1.接受参数
        target = request.json.get('target')
        # 目标用户不能为自己
        if target == g.user_id:
            abort(400)
        # 3.业务逻辑

        try:
            # 查询目标用户
            target_user = User.query.get(target)
        except Exception as e:
            current_app.logger.error(e)
        if target_user is None:
            abort(404)
        # 3.数据入库
        # 如果数据库已经存在数据的时候再次使用添加数据会报错   需要使用更新方法
        relation = Relation()
        relation.user_id = g.user_id
        relation.target_user_id = target
        relation.relation = Relation.RELATION.FOLLOW
        try:
            db.session.add(relation)
            db.session.commit()
        except Exception as e:
            #  如果要插入的字段  数据库里面有 就不能再插入 事物使用暴力回归  然后再使用更新方法 更新字段即可
            db.session.rollback()
            Relation.query.filter(Relation.user_id == g.user_id,
                                  Relation.target_user_id == target).update({'relation': Relation.RELATION.FOLLOW})
            db.session.commit()
        # 将关注数据存入redis数据库中
        from common.cache.user import UserFollowCache
        UserFollowCache(g.user_id).update(target)
        # 4.响应
        return {'target':target}

# 取消关注用户
'''
需求
    登录用户取消关注用户
前端
    ajax请求 携带token
后端
    接口文档
    请求方式：delete
    请求路径：/user/followings/<int:target>/
    请求参数：token 请求头   target路径传参
    响应：{}
'''
from common.cache.user import UserFollowCache
class UnFollowResource(Resource):
    # 必须是登录用户
    method_decorators = [login_required]
    def delete(self,target):
        # 接受参数
        # 校验参数
        # 更新状态
        rel = Relation.query.filter(
            Relation.user_id == g.user_id,
            Relation.target_user_id == target
        ).first()
        if rel:
            # 判断是否有查询结果---如果有代表两个用户之间有关系---更新缓存----没有关系不能点取消关注abort
            rel.relation=Relation.RELATION.DELETE
            db.session.add(rel)
            db.session.commit()
            # 更新缓存
            # 更新完mysql数据库中的 用户关系表之后  还需要去redis关注用户表中删除登录用户关注的这个作者的id字段
            UserFollowCache(g.user_id).update(target,action=0)
            # 返回
            return {'target':target}
        else:
            abort(400)
# 用户浏览历史记录
from common.cache.article import ArticleDetailCache
from common.cache.user import UserReadingHistoryCache
class ReadingHistoryResource(Resource):
    method_decorators = [login_required]
    def get(self):
        '''
        1.必须是登录用户
        2.接受参数
        3.校验参数
        4.业务逻辑
        5.响应
        :return:
        '''
        # 1.必须是登录用户
        user_id = g.user_id
        # 2.接受参数
        page = request.args.get('page')
        per_page = request.args.get('per_page')
        if page:
            page = int(page)
        else:
            page = 1
        if per_page:
            per_page = int(per_page)
        else:
            per_page =10
        # 3.获取阅读文章缓存的数据
        art_ids = UserReadingHistoryCache(user_id).get_ids(page,per_page)
        results = []
        for art_id in art_ids:
            article = ArticleDetailCache(article_id=art_id).get_data()
            results.append(article)
        count = UserReadingHistoryCache(user_id).get_total()
        # 5.响应
        return {
            'page': page,
            'per_page': per_page,
            'total_count': count,
            'results': results
        }
# 用户关注列表记录
class FollowingsResource(Resource):
    method_decorators = [login_required]
    # 用户关注列表展示
    def get(self):
        user_id = g.user_id
        page = request.args.get('page')
        per_page = request.args.get('per_page')
        if page:
            page = int(page)
        else:
            page = 1
        if per_page:
            per_page = int(per_page)
        else:
            per_page = 10
        count = UserFollowCache(user_id).get_total()
        art_user_ids = UserFollowCache(user_id).get_ids(page,per_page)
        results = []

        # 判断是否互相关注
        fans = UserFansCache(user_id).get_ids(page, per_page)

        for art_user_id in art_user_ids:
            art_user = UserinfoCache(user_id=art_user_id).get()

            results.append({
                'id':art_user.get('id'),
                'name':art_user.get('name'),
                'photo':art_user.get('photo'),
                'fans_count':art_user.get('fans_count'),
                'mutual_follow':art_user.get('id') in fans
            })
        return {
            "total_count": count,
            "page": page,
            "per_page": per_page,
            "results": results
        }
# 用户粉丝列表展示
# from common.cache.user import UserFansCache
class FansResource(Resource):
    method_decorators = [login_required]
    def get(self):
        user_id = g.user_id
        page = request.args.get('page')
        per_page = request.args.get('per_page')
        if page:
            page = int(page)
        else:
            page = 1
        if per_page:
            per_page = int(per_page)
        else:
            per_page = 10
        count = UserFansCache(user_id).get_total()
        fan_ids= UserFansCache(user_id).get_ids(page,per_page)

        # 判断是否互相关注---获取到用户关注的缓存列表
        follow_ids=UserFollowCache(user_id).get_ids(page,per_page)
        results = []
        for fan_id in fan_ids:
            fan = UserinfoCache(user_id=fan_id).get()

            results.append({
                'id': fan.get('id'),
                'name': fan.get('name'),
                'photo': fan.get('photo'),
                'fans_count': fan.get('fans_count'),
                'mutual_follow': fan.get('id') in follow_ids  # 判断粉丝的id在不在关注的用户列表中
            })
        return {
            "total_count": count,
            "page": page,
            "per_page": per_page,
            "results": results
        }